package creatingPattern.prototype;

/**
 * @Author: Alex Hu
 * Date: 2020/2/22 4:00 下午
 * Content:
 */

import java.util.HashMap;
import java.util.Scanner;

/**
 * 形状接口
 * 设计意图：定义形状的基本操作
 * 使用场景：当需要统一管理不同类型的形状时使用
 */
interface Shape extends Cloneable {
    /**
     * 计算面积
     * 设计意图：定义形状计算面积的方法
     * 使用场景：当需要计算形状面积时调用
     */
    void countArea();

    /**
     * 克隆对象
     * 设计意图：实现对象的复制功能
     * 使用场景：当需要创建对象的副本时调用
     * @return 返回克隆后的对象
     */
    Object clone();
}

/**
 * 圆形类
 * 设计意图：实现圆形形状的具体功能
 * 使用场景：当需要创建圆形对象时使用
 */
class Circle implements Shape {
    /**
     * 计算圆形面积
     * 设计意图：实现圆形面积的计算
     * 使用场景：当需要计算圆形面积时调用
     */
    public void countArea() {
        int r = 0;
        System.out.print("这是一个圆，请输入圆的半径：");
        Scanner input = new Scanner(System.in);
        r = input.nextInt();
        System.out.println("该圆的面积=" + 3.1415 * r * r + "\n");
    }

    /**
     * 克隆圆形对象
     * 设计意图：实现圆形对象的复制
     * 使用场景：当需要创建圆形对象的副本时调用
     * @return 返回克隆后的圆形对象
     */
    public Object clone() {
        Circle w = null;
        try {
            w = (Circle) super.clone();
        } catch (CloneNotSupportedException e) {
            System.out.println("拷贝圆失败!");
        }
        return w;
    }
}

/**
 * 正方形类
 * 设计意图：实现正方形形状的具体功能
 * 使用场景：当需要创建正方形对象时使用
 */
class Square implements Shape {
    /**
     * 计算正方形面积
     * 设计意图：实现正方形面积的计算
     * 使用场景：当需要计算正方形面积时调用
     */
    public void countArea() {
        int a = 0;
        System.out.print("这是一个正方形，请输入它的边长：");
        Scanner input = new Scanner(System.in);
        a = input.nextInt();
        System.out.println("该正方形的面积=" + a * a + "\n");
    }

    /**
     * 克隆正方形对象
     * 设计意图：实现正方形对象的复制
     * 使用场景：当需要创建正方形对象的副本时调用
     * @return 返回克隆后的正方形对象
     */
    public Object clone() {
        Square b = null;
        try {
            b = (Square) super.clone();
        } catch (CloneNotSupportedException e) {
            System.out.println("拷贝正方形失败!");
        }
        return b;
    }
}

/**
 * 原型管理器
 * 设计意图：管理不同类型的原型对象
 * 使用场景：当需要统一管理多个原型对象时使用
 */
class ProtoTypeManager {
    /**
     * 原型对象映射表
     * 设计意图：存储不同类型的原型对象
     * 使用场景：当需要管理多个原型对象时使用
     */
    private HashMap<String, Shape> ht = new HashMap<String, Shape>();

    /**
     * 构造函数
     * 设计意图：初始化原型对象
     * 使用场景：当需要创建原型管理器时调用
     */
    public ProtoTypeManager() {
        ht.put("Circle", new Circle());
        ht.put("Square", new Square());
    }

    /**
     * 添加原型对象
     * 设计意图：向管理器中添加新的原型对象
     * 使用场景：当需要扩展原型对象类型时调用
     * @param key 原型对象的键
     * @param obj 原型对象
     */
    public void addshape(String key, Shape obj) {
        ht.put(key, obj);
    }

    /**
     * 获取原型对象
     * 设计意图：获取并克隆原型对象
     * 使用场景：当需要创建新的形状对象时调用
     * @param key 原型对象的键
     * @return 返回克隆后的原型对象
     */
    public Shape getShape(String key) {
        Shape temp = ht.get(key);
        return (Shape) temp.clone();
    }
}

/**
 * 主方法：演示原型模式
 * 设计意图：通过用户交互展示原型模式的使用
 * 使用场景：当需要测试或演示原型模式时调用
 * @param args 命令行参数
 */
public class ProtoTypeShape {
    public static void main(String[] args) {
        ProtoTypeManager pm = new ProtoTypeManager();
        Shape obj1 = (Circle) pm.getShape("Circle");
        obj1.countArea();
        Shape obj2 = (Shape) pm.getShape("Square");
        obj2.countArea();
    }
}
